/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.icee.myth.server.bill;

import com.icee.myth.common.messageQueue.DBMessageQueue;
import com.icee.myth.common.messageQueue.ServerMessageQueue;
import com.icee.myth.log.GameLogger;
import com.icee.myth.log.message.FileDebugGameLogMessage;
import com.icee.myth.log.message.builder.GameLogMessageBuilder;
import com.icee.myth.server.GameServer;
import com.icee.myth.server.message.dbMessage.builder.MapDBMessageBuilder;
import com.icee.myth.server.message.serverMessage.builder.MapMessageBuilder;
import com.icee.myth.server.oauth.OAuthHelper;
import com.icee.myth.utils.Consts;
import com.icee.myth.utils.StackTraceUtil;
import net.oauth.OAuthMessage;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;

/**
 *
 * @author yangyi
 */
public class Bill implements Runnable {

    public String passport;
    public int playerId;

    public Bill(int playerId, String passport) {
        this.playerId = playerId;
        this.passport = passport;
    }

    @Override
    public void run() {
        try {            
            if (passport != null) { //TODO: 从web方式登录不可能为null
                Order order = GameServer.INSTANCE.billings.get(passport);
                if (order != null) {
                    //处理旧订单
                    JsonBillTransactionRetData retData = transaction(order);
                    if (retData == null) {
                        //重试一次
                        retData = transaction(order);
                    }

                    if (retData != null) {
                        //success
                        ServerMessageQueue.queue().offer(MapMessageBuilder.buildBillResultMessage(playerId, passport, order, retData.status));
                    } else {
                        GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                "bill tranaction error orderno:" + order.no));
                    }
                } else {                    
                    //查询充值记录，生成新订单并处理
                    JsonBillGetAssetRetData retData = getAsset(passport, GameServer.INSTANCE.regionId);
                    if (retData == null || retData.status != 0) {
                        retData = getAsset(passport, GameServer.INSTANCE.regionId);
                    }
                    if (retData != null && retData.assetList != null && retData.status == 0) {
                        int amount = 0;
                        int currencyId = -1;
                        int price = 0;
                        String goodsId = "";
                        boolean isGoodsAviable = false;
                        for (AssetDetailData assetDetailData : retData.assetList) {                            
                            if (isGoodsAviable == true) {
                                break;
                            }
                            for (int i = 0 ; i < BillStoreTemplates.INSTANCE.billStoreTemplates.length; i++){
                                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                        BillStoreTemplates.INSTANCE.billStoreTemplates[i].goodsId));
                                if (assetDetailData.goodsId.equals(BillStoreTemplates.INSTANCE.billStoreTemplates[i].goodsId)){
                                    currencyId = BillStoreTemplates.INSTANCE.billStoreTemplates[i].id;

                                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                        "currencyId:" + currencyId));

                                    price = BillStoreTemplates.INSTANCE.billStoreTemplates[i].yellowSoulNum;
                                    goodsId = assetDetailData.goodsId;
                                    amount = assetDetailData.num;
                                    isGoodsAviable = true;
                                    break;
                                }
                            }
                        }
                        /*
                        if (amount <= 0) {
                            //没有人民币
                            amount = retData.yellowsoul;
                            currencyId = 50;
                        }*/
                        if (amount > 0) {
                            String orderno = getOrderno();
                            String memo = "consumer";
                            order = new Order(orderno, currencyId, goodsId, amount, price, memo);
                            if (GameServer.INSTANCE.billings.putIfAbsent(passport, order) == null) {
                                DBMessageQueue.queue().offer(MapDBMessageBuilder.buildSaveBillDBMessage(playerId, passport, order, 0, Consts.BILL_STEP_START));
                                JsonBillTransactionRetData transactionRetData = transaction(order);
                                if (transactionRetData == null) {
                                    transactionRetData = transaction(order);
                                }

                                if (transactionRetData != null) {
                                    //success
                                    ServerMessageQueue.queue().offer(MapMessageBuilder.buildBillResultMessage(playerId, passport, order, transactionRetData.status));
                                } else {
                                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                            "bill tranaction error orderno:" + order.no));
                                }
                            } else {
                                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                        "Handle more than one passport[" + passport + "]'s bill in the same time."));
                            }
                        } else {
                            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_DEBUG,
                                        "bill get asset no money"));
                        }
                    } else {
                        GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                "bill get asset error passport:" + passport + ", errmsg:" + ((retData != null) ? retData.error : "")));
                    }
                }
            } else {
                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                        "bill get asset error passport is null"));
            }
        } catch (Exception e) {
            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                    StackTraceUtil.getStackTrace(e)));
        }
    }

    private JsonBillTransactionRetData transaction(Order order) {
        OAuthHelper oAuthHelper = GameServer.INSTANCE.oAuthHelper;
        Properties paramProps = new Properties();
        paramProps.setProperty("oauth_token", "");
        paramProps.setProperty("userid", passport);
        paramProps.setProperty("currencyid", "" + order.goodsId);
        paramProps.setProperty("amount", "" + order.amount);
        paramProps.setProperty("memo", order.memo);
        paramProps.setProperty("outordernumber", order.no);
        paramProps.setProperty("regionid", GameServer.INSTANCE.regionId);
        try {
            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_DEBUG,
                    "Send bill transaction:" + paramProps.toString() + " to: " + GameServer.INSTANCE.billServerTransactionAddress));

            // memo=consumer, userid=Ad2, oauth_token=, outordernumber=0_1384620605236_Ad2, amount=5000, currencyid=ptk_sc_20, regionid=xxx
            OAuthMessage response = oAuthHelper.sendRequest(paramProps, GameServer.INSTANCE.billServerTransactionAddress);
            String content = response.readBodyAsString();
            JSONObject jobj = (JSONObject) JSONValue.parse(content);

            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_DEBUG,
                    "Send bill transaction return:" + content));

            return new JsonBillTransactionRetData((int) (long) (Long) jobj.get("status"), (String) jobj.get("error"));
        } catch (Exception ex) {
            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                    "Send bill tranaction error: " + StackTraceUtil.getStackTrace(ex)));
            return null;
        }
    }

    private JsonBillGetAssetRetData getAsset(String passport, String regionId) {
        OAuthHelper oAuthHelper = GameServer.INSTANCE.oAuthHelper;
        Properties paramProps = new Properties();
        paramProps.setProperty("oauth_token", "");
        paramProps.setProperty("userid", passport);
        paramProps.setProperty("regionid", regionId);
        try {
            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_DEBUG,
                    "Send bill getAsset:" + paramProps.toString() + " to: " + GameServer.INSTANCE.billServerGetAssetAddress));

            // {userid=Ad2, oauth_token=, regionid=xxx}
            OAuthMessage response = oAuthHelper.sendRequest(paramProps, GameServer.INSTANCE.billServerGetAssetAddress);
            String content = response.readBodyAsString();

            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_DEBUG,
                    "Bill getAsset return content:" + content));

            // {"data":{1001:5000}}
            JSONObject jobj = (JSONObject) JSONValue.parse(content);
            JSONObject moneyJSONObject = (JSONObject) (jobj.get("data"));
            if (moneyJSONObject != null) {
                ArrayList<AssetDetailData> assetDetailData = new ArrayList<AssetDetailData>();
                Set<String> key = moneyJSONObject.keySet();

                for (Iterator it = key.iterator(); it.hasNext();) {
                    String goodsId = (String) it.next();
                    int goodsNum = (int) Math.floor(Double.parseDouble((String) moneyJSONObject.get(goodsId)));
                    if (goodsNum > 0){
                        assetDetailData.add(new AssetDetailData(goodsId, goodsNum));
                    }
                }
                return new JsonBillGetAssetRetData((int) (long) (Long) jobj.get("status"), assetDetailData, (String) jobj.get("error"));

                /*
                int rmb = 0;
                if (moneyJSONObject.get("1") != null) {
                    rmb = (int) (long) (Long) moneyJSONObject.get("1");
                }
                int yellowsoul = 0;
                if (moneyJSONObject.get("50") != null) {
                    yellowsoul = (int) Math.floor(Double.parseDouble((String) moneyJSONObject.get("50")));
                }

                return new JsonBillGetAssetRetData((int) (long) (Long) jobj.get("status"), rmb, yellowsoul, (String) jobj.get("error"));
                 */
            }
        } catch (Exception ex) {
            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                    "JSON parse error in bill get asset." + StackTraceUtil.getStackTrace(ex)));
        }
        return null;
    }

    private String getOrderno() {
        return GameServer.INSTANCE.serverId + "_" + GameServer.INSTANCE.getCurrentTime() + "_" + passport;
    }
}
